﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CPPEI.ETL.Domain.Services
{
    public class ExtDSService
    {
        public ServiceResult<Data.ExtDSAssembly> Parse(byte[] data)
        {
            Data.ExtDSAssembly extDSAssembly = null;

            try
            {
                Assembly assembly = Assembly.Load(data);

                Type[] types = assembly.GetTypes();
                foreach (var type in types)
                {
                    if (typeof(CPPEI.ETL.DataServiceInterface.IExtDSAdapter).IsAssignableFrom(type))
                    {
                        if (extDSAssembly == null)
                        {
                            extDSAssembly = new Data.ExtDSAssembly();
                            extDSAssembly.Id = Guid.NewGuid();
                            extDSAssembly.Assembly = assembly.FullName;
                            extDSAssembly.Version = assembly.GetName().Version.ToString(4);
                        }
                        // 数据审核插件类
                        Data.ExtDSType extDsType = new Data.ExtDSType();
                        extDsType.Name = type.FullName;
                        extDsType.Id = Guid.NewGuid();
                        extDsType.Description = string.Empty;
                        extDSAssembly.Types.Add(extDsType);
                    }
                }

                if (extDSAssembly == null)
                {
                    return new ServiceResult<Data.ExtDSAssembly>(false, ErrorCode.EXTDS_NoType, ErrorCode.String(ErrorCode.EXTDS_NoType));
                }
                else
                {
                    return new ServiceResult<Data.ExtDSAssembly>(true, ErrorCode.COM_NoError, ErrorCode.String(ErrorCode.COM_NoError), extDSAssembly);

                }
            }
            catch (Exception ex)
            {
                Logger.ErrorToTag(Library.LogTAG, string.Format("加载程序集出错!", ex));

                return new ServiceResult<Data.ExtDSAssembly>(false, ErrorCode.EXTDS_NoType, ErrorCode.String(ErrorCode.EXTDS_NoType));
            }
        }

        public ServiceResult Publish(Guid assebmlyId, string assemblyName, string assemblyVersion, string typesSettings)
        {
            if (string.IsNullOrEmpty(typesSettings))
            {
                return new ServiceResult(false, ErrorCode.COM_InvalidParameter, ErrorCode.String(ErrorCode.COM_InvalidParameter));
            }

            // id,name,description,id,name,description
            string[] plugInArr = typesSettings.Split(new char[] { ',' });
            if (plugInArr.Length / 3 == 0
                || plugInArr.Length % 3 != 0)
            {
                return new ServiceResult(false, ErrorCode.DVPlugIn_InvalidPlugInSettings, ErrorCode.String(ErrorCode.DVPlugIn_InvalidPlugInSettings));
            }

            string tempAssemblyFolder = string.Format("{0}ExtDS\\Temp\\", System.Configuration.ConfigurationManager.AppSettings["AssemblyFolder"]);
            string tempFilePath = string.Format("{0}{1}.dll", tempAssemblyFolder, assebmlyId.ToString("N"));
            string assemblyFolder = string.Format("{0}ExtDS\\", System.Configuration.ConfigurationManager.AppSettings["AssemblyFolder"]);
            string filePath = string.Format("{0}{1}.dll", assemblyFolder, assemblyName);

            using (EtlDbContext dbContext = new EtlDbContext())
            {
                EntityRepository<Entities.EExtDSAssembly> dvpiaRep = new EntityRepository<Entities.EExtDSAssembly>(dbContext);
                EntityRepository<Entities.EExtDSType> dvpiRep = new EntityRepository<Entities.EExtDSType>(dbContext);

                Entities.EExtDSAssembly eDvPluginAssembly = dvpiaRep.Get(p => p.Assembly == assemblyName);
                if (eDvPluginAssembly != null)
                {
                    // 删除临时文件
                    System.IO.File.Delete(tempFilePath);
                    return new ServiceResult(false, ErrorCode.COM_OBJExist, string.Format("已存在扩展数据插件:", assemblyName));
                }
                 eDvPluginAssembly = new Entities.EExtDSAssembly();
                eDvPluginAssembly.Id = assebmlyId;
                eDvPluginAssembly.Assembly = assemblyName;
                eDvPluginAssembly.Version = assemblyVersion;

                dvpiaRep.Create(eDvPluginAssembly);

                for (int index = 0; index < plugInArr.Length; index += 3)
                {
                    Entities.EExtDSType ePlugin = new Entities.EExtDSType();
                    ePlugin.AssemblyId = assebmlyId;
                    ePlugin.Id = new Guid(plugInArr[index]);
                    ePlugin.Name = plugInArr[index + 1];
                    ePlugin.Description = plugInArr[index + 2];

                    dvpiRep.Create(ePlugin);
                }

                try
                {
                    if (dbContext.SaveChanges() > 0)
                    {
                        // 移动临时文件到正式目录
                        System.IO.File.Move(tempFilePath, filePath);

                        return new ServiceResult(true, ErrorCode.COM_NoError, ErrorCode.String(ErrorCode.COM_NoError));
                    }
                    else
                    {
                        System.IO.File.Delete(tempFilePath);
                        return new ServiceResult(false, ErrorCode.COM_DBError, ErrorCode.String(ErrorCode.COM_DBError));
                    }
                }
                catch (Exception ex)
                {
                    System.IO.File.Delete(tempFilePath);
                    Logger.ErrorToTag(Library.LogTAG, string.Format("发布外部扩展服务:{0},出错,ex:{1}!", assemblyName, ex));

                    return new ServiceResult(false, ErrorCode.COM_NoError, ErrorCode.String(ErrorCode.COM_NoError));
                }
            }
        }

        public PagedList<Entities.EExtDSAssembly> GetAssemblyList(string filter, int start, int limit)
        {
            using (EtlDbContext dbContext = new EtlDbContext())
            {
                EntityRepository<Entities.EExtDSAssembly> dvpiaRep = new EntityRepository<Entities.EExtDSAssembly>(dbContext);

                if(string.IsNullOrEmpty(filter))
                {
                    List<Entities.EExtDSAssembly> list = dbContext.Set<Entities.EExtDSAssembly>().OrderBy(p=>p.Assembly).Take(limit).Skip(start).ToList();
                    int total = dbContext.Set<Entities.EExtDSAssembly>().Count();

                    return new PagedList<Entities.EExtDSAssembly>(true, ErrorCode.COM_NoError, ErrorCode.String(ErrorCode.COM_NoError), start, limit,
                        total,
                        list);
                }
                else
                {
                    List<Entities.EExtDSAssembly> list = dbContext.Set<Entities.EExtDSAssembly>().Where(p => p.Assembly.Contains(filter)).OrderBy(p => p.Assembly).Take(limit).Skip(start).ToList();
                    int total = dbContext.Set<Entities.EExtDSAssembly>().Where(p => p.Assembly.Contains(filter)).Count();

                    return new PagedList<Entities.EExtDSAssembly>(true, ErrorCode.COM_NoError, ErrorCode.String(ErrorCode.COM_NoError), start, limit,
                        total,
                        list);
                }
            }
        }

        public PagedList<Entities.EExtDSType> GetTypeList(Guid assemblyId, int start, int limit)
        {
            if (assemblyId == Guid.Empty)
            {
                return new PagedList<Entities.EExtDSType>(false, ErrorCode.COM_InvalidParameter, ErrorCode.String(ErrorCode.COM_InvalidParameter));
            }

            using (EtlDbContext dbContext = new EtlDbContext())
            {
                EntityRepository<Entities.EExtDSType> dvpiRep = new EntityRepository<Entities.EExtDSType>(dbContext);

                List<Entities.EExtDSType> list = dvpiRep.Query(p => p.AssemblyId == assemblyId).Take(limit).Skip(start).ToList();
                int total = dvpiRep.Count();

                return new PagedList<Entities.EExtDSType>(true, ErrorCode.COM_NoError, ErrorCode.String(ErrorCode.COM_NoError), start, limit, total, list);
            }
        }
    }
}
